package com.blockchain.coupon.rpc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;
import net.sf.json.JSONArray;
import java.util.ArrayList;
import net.sf.json.JSONObject;

import com.blockchain.coupon.sha3.Sha3;
import com.blockchain.coupon.util.ReadAccount;
import com.sun.jersey.api.client.WebResource;

public class Web3 {
	
	private static WebResource r = WebResourceObj.getWebResource();
	private static Map<String,Map<String,String>> map = new HashMap<String,Map<String,String>>();
	
	
	public static void init(){
		InputStream in=Web3.class.getClassLoader().getResourceAsStream("abi/MainABI.txt");
		addABIFile(in, "Main");
		in=Web3.class.getClassLoader().getResourceAsStream("abi/MerchantABI.txt");
		addABIFile(in, "Merchant");
		in=Web3.class.getClassLoader().getResourceAsStream("abi/CouponABI.txt");
		addABIFile(in, "Coupon");
		in=Web3.class.getClassLoader().getResourceAsStream("abi/BankABI.txt");
	    addABIFile(in, "Bank");
		in=Web3.class.getClassLoader().getResourceAsStream("abi/ConsumerABI.txt");
	    addABIFile(in, "Consumer");
	}
	
	public static void main(String[] args) throws IOException{
		
//		addABIFile("F:/zju/BlockChain/czbankProgram/Contract/ABI/MainABI.txt", "Main");
//		addABIFile("F:/zju/BlockChain/czbankProgram/Contract/ABI/MerchantABI.txt", "Merchant");
//		addABIFile("F:/zju/BlockChain/czbankProgram/Contract/ABI/BankABI.txt", "Bank");
//		addABIFile("F:/zju/BlockChain/czbankProgram/Contract/ABI/CouponABI.txt", "Coupon");
//		addABIFile("F:/zju/BlockChain/czbankProgram/Contract/ABI/ConsumerABI.txt", "Consumer");
		
		
		
//		主合约地址：    0xde7f563c45db2bb8ca9455f347620999c61e40e0
//		银行合约地址：0xb8cb7c19fa98ef552b5ed26c878fc443289c9375
//		Merchanth合约地址:0x48944e22a3d616b441ca58db68db9b8f4d967dcd
//		consumer账户:0x794fc320ba9c7dd1e6b8bea869e890199e3e8bfa
		
//		String functionName = "Main.createMerchant";
//		String[] content = {"0xc92c4bb2312b08d525221ef5834880fb4d03015e"};  //商户公钥
//		String from = "0x527613b34f50e18987c4ad6402357d6724705577";  //交易发送方
//		String to = "0xd9aaeee33b67342138d3ae6562a4c711fe9de024";  //主合约地址
//		sendTransactionMap(functionName, content, from, to);
		
//		String functionName = "Main.getMerchantLatest";
//		String[] content = null;  //商户公钥
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";  //交易发送方
//		String to = "0xde7f563c45db2bb8ca9455f347620999c61e40e0";  //主合约地址
//		getValueMap(functionName, content, from, to);
		
	
//		String functionName = "Main.approve";
//		String[] content = {"1","0x48944e22a3d616b441ca58db68db9b8f4d967dcd","10000","true"};
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";
//		String to = "0xde7f563c45db2bb8ca9455f347620999c61e40e0";//main contract address
//		sendTransactionMap(functionName, content, from, to);
		init();
		String functionName = "Merchant.getBalance";
		String[] content = null;
		String from = ReadAccount.getAccount("merchantAccount");
		String to = "0x1c0f3044e607240ede9048836fcda121607bfb8e";
		getValueMap(functionName, content, from, to);	
		
//		String functionName = "Bank.setPermissions";
//		String[] content = {"true","true","0x48944e22a3d616b441ca58db68db9b8f4d967dcd","0x36168ff2e45e6906601ae696a26e0a0f77d3a778"};
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";
//		String to = "0x85311503b05bccd86973bf290870879156c94ae9";//bank contract address
//		sendTransactionMap(functionName, content, from, to);
		
//		String functionName = "Merchant.getPermission";
//		String[] content = null;
//		String from = "0xc92c4bb2312b08d525221ef5834880fb4d03015e";
//		String to = "0x5842cc032325f871c916ba57ab68ae2c96be88d7";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Merchant.issueMany";
//		String[] content = {"10","2016-09-05","2017-09-23","10"};
//		String from = ReadAccount.getAccount("merchantAccount");
//		String to = "0x8f5f34c0fd4cadb8209d7b9eed83d58bae3527bb";//Merchant contract address
//		sendTransactionMap(functionName, content, from, to);
//		
//		
//		sendTransactionMap(functionName, content, from, to);
	
//		String functionName = "Merchant.getNotIssuedQuantity";
//		String[] content = null;
//		String from = ReadAccount.getAccount("merchantAccount");
//		String to = "0x8f5f34c0fd4cadb8209d7b9eed83d58bae3527bb";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Coupon.getState";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0xfae712c0b75b6a046c36935b55bc72dca14b813e";
//		getValueMap(functionName, content, from, to);

//		Consumer账户:0x794fc320ba9c7dd1e6b8bea869e890199e3e8bfa
//		String functionName = "Merchant.grant";
//		String[] content = {"30","350","0x794fc320ba9c7dd1e6b8bea869e890199e3e8bfa","2016"};
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0x48944e22a3d616b441ca58db68db9b8f4d967dcd";//Merchant contract address
//		sendTransactionMap(functionName, content, from, to);
		
//		String functionName = "Merchant.getLatestNotIssuedCouponByQuantity";
//		String[] content = {"20"};
//		String from = ReadAccount.getAccount("merchantAccount");
//		String to = "0x8f5f34c0fd4cadb8209d7b9eed83d58bae3527bb";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Merchant.getIssuedCoupon";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0x48944e22a3d616b441ca58db68db9b8f4d967dcd";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Consumer.getCoupons";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0x794fc320ba9c7dd1e6b8bea869e890199e3e8bfa";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Coupon.getState";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0xfae712c0b75b6a046c36935b55bc72dca14b813e";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Coupon.getRecording";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0xfae712c0b75b6a046c36935b55bc72dca14b813e";
//		getValueMap(functionName, content, from, to);
		
//		Consumer:0x794fc320ba9c7dd1e6b8bea869e890199e3e8bfa
//		String functionName = "Merchant.payConfirm";
//		String[] content = {"0x794fc320ba9c7dd1e6b8bea869e890199e3e8bfa","[0xfae712c0b75b6a046c36935b55bc72dca14b813e,0xfef40bf82c84da7e09d68f00a945de0d31d8ad09]"};
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0x48944e22a3d616b441ca58db68db9b8f4d967dcd";//Merchant contract address
//		sendTransactionMap(functionName, content, from, to);
		
//		String functionName = "Merchant.getSettlementCoupon";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0x48944e22a3d616b441ca58db68db9b8f4d967dcd";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Merchant.getBalance";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0x48944e22a3d616b441ca58db68db9b8f4d967dcd";
//		getValueMap(functionName, content, from, to);	
		
//		String functionName = "Consumer.getCoupons";
//		String[] content = null;
//		String from =ReadAccount.getAccount("consumerAccount");
//		String to = "0x5d9618f6bef12658378491f14c19af885015cb2e";
//		getValueMap(functionName, content, from, to);
		
//		String functionName = "Coupon.getState";
//		String[] content = null;
//		String from = "0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808";
//		String to = "0xfae712c0b75b6a046c36935b55bc72dca14b813e";
//		getValueMap(functionName, content, from, to);
		
		
/////////////////////////////////////////////		
//		String[] type = {"address"};
//		String functionName = "Main.createMerchant";
//		String[] content = {"0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808"};  //商户公钥
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";  //交易发送方
//		String to = "0xe3174ac1b2e98373162d433ae895e3bea5f7de03";  //主合约地址
//		sendTransactionMap(functionName, content, from, to);
//		sendTransaction(functionName, type, content, from, to);
	

//		String functionName = "getMerchantLatest";
//		String[] type = null;
//		String[] content = null;
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";
//		String to = "0xe3174ac1b2e98373162d433ae895e3bea5f7de03";
//		getValue(functionName, type, content, from, to);
		
//		String functionName = "getBalance";
//		String[] type = null;
//		String[] content = null;
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";
//		String to = "0xd070663d63963faaaa6c674f3a15445f91a913d4";
//		getValue(functionName, type, content, from, to);
		
//		String functionName = "eth_compileSolidity";
//		Boolean flag = null;
//		String object = null;
//		String[] content={"contract Main{ address owner; address[] merchants; address banker; function Main(){ address operatorAddr = 0x123; address checkerAddr = 0x456; owner = msg.sender; banker = new Bank(operatorAddr,checkerAddr,msg.sender); } modifier onlyOwner(){ if(msg.sender!=owner) throw; _ } function createMerchant(address merchant) onlyOwner{ merchants.push(new Merchant(owner,merchant)); } function approve( bytes signature, address _merchant, uint value, bool isAdd ) onlyOwner{ Bank bank = Bank(banker); bank.approve(signature,_merchant,value,isAdd,msg.sender); } function getBankAddress() constant returns(address){ return banker; } function getMerchants() constant returns(address[]){ return merchants; } function getMerchantLatest() constant returns(address){ return merchants[merchants.length-1]; } } contract Bank{ address operatorAddr; address checkerAddr; address owner; function Bank(address opKey,address ckKey,address sender){ operatorAddr = opKey; checkerAddr = ckKey; owner = sender; } function approve( bytes signature, address _merchant, uint value, bool isAdd, address sender ) onlyOwner(sender) { if(check(signature)){ Merchant merchant = Merchant(_merchant); merchant.updateBalance(value,isAdd); } } function setPermissions(bool _issuePermission,bool _chargePermission,address _merchant,address sender) onlyOwner(sender){ Merchant merchant = Merchant(_merchant); merchant.setPermissions(_issuePermission,_chargePermission,owner); } function check(bytes signature) returns(bool ){ bool result = true; return result; } modifier onlyOwner(address sender){ if(sender!=owner) throw; _ } } contract Merchant { address banker; address owner; uint balance; bool issuePermission; bool chargePermission; address[] issuedCoupon; address[] notIssuedCoupon; address[] settlementCoupon; address[] latestIssue; address[] latestNotIssue; function Merchant(address bank,address sender ){ banker = bank; owner = sender; } modifier onlyOwner(){ if(msg.sender!=owner) throw; _ } modifier onlyBanker(address bankerAccount) { if(bankerAccount!=banker) throw; _ } function issue(uint value,bytes validStart,bytes validEnd) onlyOwner { notIssuedCoupon.push(new Coupon(value,validStart,validEnd,owner)); balance = balance - value; } function issueMany(uint value,bytes validStart,bytes validEnd,uint quantity) onlyOwner { if(issuePermission!=true) throw; for(uint i=0;i<quantity;i++){ issue(value,validStart,validEnd); } } function queryCouponQuantities() onlyOwner constant returns(uint,uint,uint){ } function getNotIssuedCoupon() constant returns(address[]){ return notIssuedCoupon; } function getIssuedCoupon() constant returns(address[]){ return issuedCoupon; } function getSettlementCoupon() constant returns(address[]){ return settlementCoupon; } function getNotIssuedQuantity() constant returns(uint){ return notIssuedCoupon.length; } function getIssuedCouponQuantity() constant returns(uint){ return issuedCoupon.length; } function getSettlementCouponQuantity() constant returns(uint){ return settlementCoupon.length; } function getLatestIssuedCouponByQuantity(uint quantity) constant returns(address[]){ delete latestIssue; for(uint i=issuedCoupon.length-quantity;i<issuedCoupon.length;i++){ latestIssue.push(issuedCoupon[i]); } return latestIssue; } function getLatestNotIssuedCouponByQuantity(uint quantity) constant returns(address[]){ delete latestNotIssue; for(uint i=notIssuedCoupon.length-quantity;i<notIssuedCoupon.length;i++){ latestNotIssue.push(notIssuedCoupon[i]); } return latestNotIssue; } function getAllCouponsValue() onlyOwner constant returns(uint,uint,uint,uint){ } function terminateIssue() onlyOwner{ } function fundSettlement() { } function grant( uint value, uint consumptionValue, address _consumer, bytes date ) onlyOwner { uint currentQuantity = notIssuedCoupon.length; if(currentQuantity<0) throw; Coupon c = Coupon(notIssuedCoupon[currentQuantity-1]); uint couponValue = c.getValue(); uint quantity = value/couponValue; if(currentQuantity<quantity) throw; for(uint i=0;i<quantity;i++){ address couponAddress = notIssuedCoupon[currentQuantity-1]; Coupon coupon = Coupon(couponAddress); coupon.consumeRecording(date,_consumer,consumptionValue); coupon.setState(Coupon.CouponState.Granted); issuedCoupon.push(couponAddress); currentQuantity = currentQuantity - 1; Consumer consumer = Consumer(_consumer); consumer.addCoupon(couponAddress); } notIssuedCoupon.length = notIssuedCoupon.length - quantity; } function setPermissions( bool _issuePermission, bool _chargePermission, address bankAccount ) onlyBanker(bankAccount) { issuePermission = _issuePermission; chargePermission = _chargePermission; } function setAccount() { } function getPermission() constant returns(bool){ return issuePermission; } function payConfirm( address _consumer, address[] couponAddress ) { if(!chargePermission) throw; Consumer consumer = Consumer(_consumer); consumer.payCoupon(couponAddress); for(uint i=0;i<couponAddress.length;i++){ settlementCoupon.push(couponAddress[i]); Coupon c = Coupon(couponAddress[i]); balance = balance + c.getValue(); } } function updateBalance(uint value,bool isAdd){ if(isAdd){ balance = balance + value; }else{ balance = balance - value; } } function getBalance() constant returns(uint){ return balance; } } contract Coupon { address publisher; address owner; uint value; bytes validStart; bytes validEnd; struct Consumption { bytes date; address consumer; uint amount; } Consumption consumption; enum CouponState {Issuing,Granted,Used,Withdrawn} CouponState state; function Coupon( uint _value, bytes _validStart, bytes _validEnd, address _publisher ) { value = _value; validStart = _validStart; validEnd = _validEnd; publisher = _publisher; owner = _publisher; state = CouponState.Issuing; } function consumeRecording( bytes date, address consumer, uint amount ) { consumption = Consumption(date,consumer,amount); } function transfer( address receiver ) { } function payApply( address merchant ) { } function getValue() constant returns(uint){ return value; } function setState(CouponState st){ state = st; } function getState() constant returns(CouponState){ return state; } function getRecording() constant returns(bytes,address,uint){ return (consumption.date,consumption.consumer,consumption.amount); } } contract Consumer { address banker; address owner; bool state; address[] coupons; function Consumer(){ owner = msg.sender; } function getCoupon( Coupon coupon ){ } function setState(bool _state){ } function queryCoupons(){ } function addCoupon(address coupon){ coupons.push(coupon); } function payCoupon(address[] coups) { for(uint i=0;i<coups.length;i++){ Coupon c = Coupon(coups[i]); c.setState(Coupon.CouponState.Used); for(uint j=0;j<coupons.length;j++){ if(coupons[j]==coups[i]){ coupons[j] = 0; } } } } function getCoupons() constant returns(address[]){ return coupons; } }"};
//		String result=Web3.universalCall(functionName, object, content, flag);

		
//		String functionName = "Main.approve";
//		String[] type = {"bytes","address[]","uint[]","bool"};
//		String[] content = {"1","[0xd070663d63963faaaa6c674f3a15445f91a913d4,0xd070663d63963faaaa6c674f3a15445f91a913d5]","[100,50]","true"};
//		String[] type = {"bytes","address","uint","bool"};
//		String functionName = "Main.approve";
//		String[] content = {"1","0x2f45793cc3ce5fa7d3d3f1d6dbf3769fc84ce2db","100","true"};
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";
//		String to = "0xe3174ac1b2e98373162d433ae895e3bea5f7de03";//main contract address
//		sendTransactionMap(functionName, content, from, to);
//		sendTransaction(functionName, type, content, from, to);
//		System.out.println(Integer.toHexString(4712388));
		

//////>????????? . 不支持
//		String[] type = null;
//		String functionName = "Merchant.getBalance";
//		String[] content = null;
//		String from = "0x36168ff2e45e6906601ae696a26e0a0f77d3a778";
//		String to = "0x2f45793cc3ce5fa7d3d3f1d6dbf3769fc84ce2db";
//		getValueMap(functionName, content, from, to);

//		getValue(functionName, type, content, from, to);
		
		
//		String object = "{\"from\":\"123\",\"to\":\"45\"}";
//		String functionName = "eth_getBalance";
//		Boolean flag = null;
//		String object = null;
//		String[] content = {"0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808","latest"};
//		universalCall(functionName, object, content, flag);
		

//		String functionName = "eth_getBalance";
//		Boolean flag = null;
////		String object = "{\"from\":\"123\",\"to\":\"45\"}";
//		String object = null;
//		String[] content = {"0xa8a12a35afc9d6dbffa2d40ce08a1f78a4619808","latest"};
//		universalCall(functionName, object, content, flag);
		
   
//		String functionName = "eth_getTransactionReceipt";
//		Boolean flag = null;
//		String object = null;
//		String[] content = {"0x2532a14708bd2e7f2badebc2bc257a03b4abcd51b8e84d3071acec4c2a90ec4d"};
//		Web3.universalCall(functionName, object, content, flag);

	
		
//		System.out.println(getData("approve",type,content));
		
//		String s="0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000wcasdcasdcwweqweqcwcdscefqwcwdcscasdcded000000000000000000000000cscsdcwiefiqwevnwivnweivivnwenwccwccwced";
//		System.out.println(decodeReturnValue("address[]", s));
	}
	
	public static String sendTransactionMap(String abFunctionName,String[] content,String from,String to){
		String[] contractAndFunction = abFunctionName.split("\\.");
		if(map.isEmpty()) {
			System.out.println("map is null");
			return "";
		}
		System.out.println(contractAndFunction[0]);
		String contractName = contractAndFunction[0];
		if(!map.containsKey(contractName)){
			System.out.println("contract is not exist");
			return "";
		}
		Map<String,String> funs = map.get(contractName);
		String functionName = contractAndFunction[1];
		if(!funs.containsKey(functionName)) {
			System.out.println("contract \""+contractName+"\" does not have \""+functionName+"\"  function");
			return "";
		}
		String[] types = funs.get(functionName).split(",");
		if(types.length==0)
			types = null;
		return sendTransaction(functionName, types, content, from, to);
	}
	
	public static String getValueMap(String abFunctionName,String[] content,String from,String to){
		String[] contractAndFunction = abFunctionName.split("\\.");
		if(map.isEmpty()) {
			System.out.println("map is null");
			return "";
		}
		System.out.println(contractAndFunction[0]);
		String contractName = contractAndFunction[0];
		if(!map.containsKey(contractName)){
			System.out.println("contract is not exist");
			return "";
		}
		Map<String,String> funs = map.get(contractName);
		String functionName = contractAndFunction[1];
		if(!funs.containsKey(functionName)) {
			System.out.println("contract \""+contractName+"\" does not have \""+functionName+"\"  function");
			return "";
		}
		String[] types = funs.get(functionName).split(",");
		if(types.length==0)
			types = null;
		return getValue(functionName, types, content, from, to);
	}
	
//	发送交易执行这个方法
	public static String sendTransaction(String functionName,String[] type,String[] content,String from,String to){
		String data = getData(functionName,type,content);
		System.out.println(data);
//		String gas = getGas(from,to,data);//"0x2faf080"
		String gas = "0x47e7c4";//"0x9faf080";
		String rpc = "{\"jsonrpc\":\"2.0\",\"method\": \"eth_sendTransaction\", \"params\": [{\"from\": \""+from+"\", \"to\": \""+to+"\",\"gas\":\""+gas+"\" ,\"data\": \""+data+"\"}], \"id\": 8}";
		System.out.println(rpc);
		String response = r.accept(MediaType.APPLICATION_JSON, MediaType.TEXT_XML)
                .entity(rpc, MediaType.APPLICATION_JSON)
                .post(String.class);
		JSONObject json=JSONObject.fromObject(response);
		System.out.println(json);
	    System.out.println(json.getString("result"));
//	    返回交易哈希
	    return json.getString("result");
	}
	
	
	
	public static String getValue(String functionName,String[] type,String[] content,String from,String to){
		String data = getData(functionName,type,content);
		String rpc = "{\"jsonrpc\":\"2.0\",\"method\": \"eth_call\", \"params\": [{\"from\": \""+from+"\", \"to\": \""+to+"\",\"data\": \""+data+"\"},\"latest\"], \"id\": 8}";
		String response = r.accept(MediaType.APPLICATION_JSON, MediaType.TEXT_XML)
                .entity(rpc, MediaType.APPLICATION_JSON)
                .post(String.class);
		JSONObject json=JSONObject.fromObject(response);
		System.out.println(json.getString("result"));
		return json.getString("result");
	}
	
	
//	对方法的返回值进行解码,这个方法只能解码返回值类型是静态类型的返回值
	public static List<String> decodeReturnValue(String returnType, String data) {
		List<String > list=new ArrayList<String>();
		
		if(returnType.contains("uint")) {
			int flag = 0;
			for(int i = 2; i<data.length(); i++){
				if(!data.substring(i,i+1).equals("0")){
					flag = i;
					break;
				}
			}
			String value=data.substring(flag, data.length());
			list.add(Integer.parseInt(value,16)+"");
			return list;
		} else if (returnType.contains("bool")) {
			list.add( data.substring(data.lastIndexOf("0")+1,data.length()).equals("")?"0":"1");
			return list;
		} else if(returnType.contains("bytes")) {
			int count=Integer.parseInt(returnType.substring(5,6));
//			除去首部的0
			 String value=data.substring(2, count*2+2);
//			 return "0x"+value;
//			转换成字符串
			 StringBuffer sb=new StringBuffer();
			 for(int i=0; i<value.length(); i=i+2){
				 int num=Integer.parseInt(value.substring(i, i+2), 16);
				 sb.append((char)num);
			 }
			 list.add(sb.toString());
			 return list;
			 
		} else if (returnType.contains("address") && !returnType.contains("[")){
			list.add("0x"+data.substring(26, data.length()));
			return list;
		} else if (returnType.contains("address[]")){ 
			int i=0;
			data=data.substring(130,data.length());
//			System.out.println("=========");
//			System.out.println(data);
//			System.out.println("=========");
			for(int count=0;count<data.length();){
				list.add("0x"+data.substring(24+64*i, 64+64*i));
				count= 64*(i+1);
				i++;
			}
			return list;
		}else{
			return list;
		}
	}
	
//	封装了系统的一些方法
	public static String universalCall(String functionName,String objStr,String[] content,Boolean flag){
		String m = "";
		if(content!=null&&content.length>0){
			StringBuffer con = new StringBuffer();
			for(int i=0;i<content.length;i++){
				con.append("\""+content[i]+"\",");
			}
			m = con.substring(0, con.length()-1);
		}
		if(objStr==null){
			objStr = "";
		}
		if(!objStr.isEmpty()&&!m.isEmpty()){
			objStr += ",";
		}
		String flagStr = "";
		
		if((!objStr.isEmpty()||!m.isEmpty())&&flag!=null){
			flagStr = ","+flag+"";
		}
		if(objStr.isEmpty()&&m.isEmpty()&&flagStr!=null)
			flagStr = ""+flag+"";
		String rpc = "{\"jsonrpc\":\"2.0\",\"method\":\""+functionName+"\",\"params\":["+objStr+m+flagStr+"],\"id\":\"8\"}";
		System.out.println(rpc);
		String response = r.accept(MediaType.APPLICATION_JSON, MediaType.TEXT_XML)
                .entity(rpc, MediaType.APPLICATION_JSON)
                .post(String.class);
		JSONObject json=JSONObject.fromObject(response);
		System.out.println(json);
		System.out.println(json.getString("result"));
		return json.getString("result");
	}
	
	public static void addABIFile(InputStream in,String contractName){
		BufferedReader br = null;
		try {
			br=new BufferedReader(new InputStreamReader(in));
			StringBuffer sb = new StringBuffer();
			String str = null;
			while((str=br.readLine())!=null){
				sb.append(str);
			}
			JSONArray json = JSONArray.fromObject(sb.toString());
			List<Map<String,Object>> lms = (List)json;
			Map<String,String> inner = new HashMap<String,String>();
			for(int i=0;i<lms.size();i++){//变脸每一个方法
				Map<String,Object> m = lms.get(i);
				Object methodName = m.get("name");
				if(methodName==null){//constructor
					methodName = contractName;
				}
				JSONArray tp = JSONArray.fromObject(m.get("inputs"));
				List<Map<String,Object>> lm = (List)tp;
				String types = "";
				for(int j=0;j<lm.size();j++){//遍历某个方法的每个参数
					types += lm.get(j).get("type")+",";
				}
				if(types.contains(",")){
					types = types.substring(0,types.length()-1);
				}
				inner.put(methodName.toString(), types);
			}
			map.put(contractName,inner);
			System.out.println(map);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(br!=null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	

//  调用平台方法，估测一笔交易需要消耗多少gas
	private static String getGas(String from,String to,String data){
		String rpc = "{\"jsonrpc\":\"2.0\",\"method\": \"eth_estimateGas\", \"params\": [{\"from\": \""+from+"\", \"data\": \""+data+"\"}], \"id\": 5}";
		String response = r.accept(MediaType.APPLICATION_JSON, MediaType.TEXT_XML)
				.entity(rpc, MediaType.APPLICATION_JSON)
				.post(String.class);
		JSONObject json=JSONObject.fromObject(response);
		System.out.println(json.getString("result"));
		return json.getString("result");
	}
	
//	对传递进入的参数进行封装
	private static String getData(String functionName,String[] type,String[] content){
		if(type==null){
			String functionId = "0x"+Sha3.sha3(functionName+"()").substring(0, 8);
			return functionId;
		}
		String functionHead = functionName+"(";
		StringBuffer dataTail = new StringBuffer();
		String curType = "";
		int curOffset = 0;
		int curIndex = 0;
		
		String dyTypes = "";
		for(int i=0;i<type.length;i++){
		///////basic type
			///type uint transfer to uint256
			if(type[i].equals("uint")) {
				type[i] = "uint256";
//				dataTail.append(convert32Bytes(Integer.toHexString(Integer.parseInt(content[i]))));
			}
			///type uint32,uint64 and so on
			if(!type[i].equals("uint")&&type[i].contains("uint")&&!type[i].contains("[")){
				dataTail.append(convert32Bytes(Integer.toHexString(Integer.parseInt(content[i]))));
			}
			if(type[i].equals("address")){
				dataTail.append(convert32Bytes(content[i].substring(2)));
			}
			///type bytes1 to bytes32
			if(!type[i].equals("bytes")&&type[i].contains("bytes")&&!type[i].contains("[")){
				dataTail.append(convertASC(content[i]));
			}
			if(type[i].equals("bool")){
				if(content[i].equals("true"))
					dataTail.append(convert32Bytes(1+""));
				if(content[i].equals("false"))
					dataTail.append(convert32Bytes(0+""));
			}
		///////dynamic type	
			if(type[i].equals("bytes")){
				if(curType.isEmpty()){
					curOffset = 32*content.length;
				}else{
					if(curType.equals("bytes")){
						curOffset += 32*2;
					}
					if(curType.startsWith("uint")&&curType.contains("[")){
						String[] str = content[curIndex].substring(1, content[curIndex].length()-1).split(",");
						curOffset += (str.length+1)*32;
					}
					if(curType.equals("address[]")){
						String[] str = content[curIndex].substring(1, content[curIndex].length()-1).split(",");
						curOffset += (str.length+1)*32;
					}
				}
				dataTail.append(convert32Bytes(Integer.toHexString(curOffset)));
				curType = "bytes";
				curIndex = i;
				dyTypes += "bytes-"+i+",";
			}
			if(type[i].contains("[")){
				String subType = type[i].substring(0, type[i].indexOf('['));
				if(subType.contains("uint")){
					if(subType.equals("uint")){
						type[i] = "uint256[]";
					}
					if(curType.isEmpty()){
						curOffset = 32*content.length;
					}else{
						if(curType.equals("bytes")){
							curOffset += 32*2;
						}
						if(curType.startsWith("uint")&&curType.contains("[")){
							String[] str = content[curIndex].substring(1, content[curIndex].length()-1).split(",");
							curOffset += (str.length+1)*32;
						}
						if(curType.equals("address[]")){
							String[] str = content[curIndex].substring(1, content[curIndex].length()-1).split(",");
							curOffset += (str.length+1)*32;
						}
					}
					dataTail.append(convert32Bytes(Integer.toHexString(curOffset)));
					curType = "uint[]";
					curIndex = i;
					dyTypes += "uint[]-"+i+",";
				}
				if(subType.contains("address")){
					if(curType.isEmpty()){
						curOffset = 32*content.length;
					}else{
						if(curType.equals("bytes")){
							curOffset += 32*2;
						}
						if(curType.startsWith("uint")&&curType.contains("[")){
							String[] str = content[curIndex].substring(1, content[curIndex].length()-1).split(",");
							curOffset += (str.length+1)*32;
						}
						if(curType.equals("address[]")){
							String[] str = content[curIndex].substring(1, content[curIndex].length()-1).split(",");
							curOffset += (str.length+1)*32;
						}
					}
					dataTail.append(convert32Bytes(Integer.toHexString(curOffset)));
					curType = "address[]";
					curIndex = i;
					dyTypes += "address[]-"+i+",";
				}
			}
			functionHead += type[i]+",";
		}
		functionHead = functionHead.substring(0, functionHead.length()-1)+")";System.out.println(functionHead);
		String functionId = "0x"+Sha3.sha3(functionHead).substring(0, 8);
		if(!dyTypes.isEmpty()){
			String[] dy = dyTypes.substring(0, dyTypes.length()-1).split(",");
			for(int i=0;i<dy.length;i++){
				if(dy[i].contains("bytes-")){
					String[] s = dy[i].split("-");
					int index = Integer.parseInt(s[1]);
					dataTail.append(convert32Bytes(Integer.toHexString(content[index].length())));
					dataTail.append(convertASC(content[index]));
				}
				if(dy[i].contains("[")){
					if(dy[i].contains("uint")){
						String[] s = dy[i].split("-");
						int index = Integer.parseInt(s[1]);
						String[] arr = content[index].substring(1, content[index].length()-1).split(",");
						dataTail.append(convert32Bytes(Integer.toHexString(arr.length)));
						for(int j=0;j<arr.length;j++){
							dataTail.append(convert32Bytes(Integer.toHexString(Integer.parseInt(arr[j]))));
						}
					}
					if(dy[i].contains("address")){
						String[] s = dy[i].split("-");
						int index = Integer.parseInt(s[1]);
						String[] arr = content[index].substring(1, content[index].length()-1).split(",");
						dataTail.append(convert32Bytes(Integer.toHexString(arr.length)));
						for(int j=0;j<arr.length;j++){
							dataTail.append(convert32Bytes(arr[j].substring(2)));
						}
					}
				}
			}
		}
		return functionId+dataTail;
	}
	

	private static String convertASC(String string) {
		String s = "";
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<string.length();i++){
			sb.append(Integer.toHexString(string.charAt(i)-'0'+'0'));
		}
		
		int len = sb.length();
		for(int i=0;i<64-len;i++){
			sb.append('0');
		}
		return sb.toString();
	}

	private static String convert32Bytes(String string) {
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<64-string.length();i++){
			sb.append('0');
		}
		return sb.toString()+string;
	}
	
}
